# coding=utf8
# 继承sdk并进行扩展
import mimetypes
import time
from io import BytesIO

import requests
from wechat_sdk import WechatBasic as WxBasic
from wechat_sdk import WechatConf
from wechat_sdk.exceptions import WechatAPIException

from zUtils.helps import random_char
from zUtils.redis import model_redis


class WechatBasic(WxBasic):
    def __init__(self, user_conf):
        self.alias = user_conf.get('alias')
        user_conf.update({
            'encrypt_mode': 'normal'
        })
        self.access_token_key = 'wechat:accessToken:{}'.format(self.alias)
        wechat_conf = WechatConf(**user_conf,
                                 access_token_getfunc=self.get_access_token_function,
                                 access_token_setfunc=self.set_access_token_function
                                 )
        super(WechatBasic, self).__init__(conf=wechat_conf)

    def get_access_token_function(self):
        """ 注意返回值为一个 Tuple，第一个元素为 access_token 的值，第二个元素为 access_token_expires_at 的值 """
        token_encode = model_redis.get(self.access_token_key)
        if not token_encode:
            get_access_token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&' \
                                   'appid={APPID}&secret={APPSECRET}'.format(APPID=self.conf.appid,
                                                                             APPSECRET=self.conf.appsecret)
            token = requests.get(get_access_token_url).json()
            if 'errcode' in token:
                raise WechatAPIException(**token)
            # todo sdk的锅，导致二次写入
            self.set_access_token_function(token['access_token'], int(time.time()) + token['expires_in'])
        else:
            token = {
                'access_token': token_encode,
                'expires_in': model_redis.ttl(self.access_token_key)
            }
        return token['access_token'], int(time.time()) + token['expires_in']

    def set_access_token_function(self, access_token, access_token_expires_at):
        model_redis.set(self.access_token_key, access_token)
        model_redis.expireat(self.access_token_key, access_token_expires_at)

    def refresh_access_token_function(self):
        """ 注意返回值为一个 Tuple，第一个元素为 access_token 的值，第二个元素为 access_token_expires_at 的值 """
        return self.get_access_token_function()

    def add_news(self, data):
        """
        新增永久图文素材
        :param data: {
                    "articles": [{
                        "title": TITLE,
                        "thumb_media_id": THUMB_MEDIA_ID,
                        "author": AUTHOR,
                        "digest": DIGEST,
                        "show_cover_pic": SHOW_COVER_PIC(0 / 1),
                        "content": CONTENT,
                        "content_source_url": CONTENT_SOURCE_URL
                    },
                    //若新增的是多图文素材，则此处应有几段articles结构，最多8段
                    ]
                }
                参数  是否必须    说明
                title	是	标题
                thumb_media_id	是	图文消息的封面图片素材id（必须是永久mediaID）
                author	是	作者
                digest	是	图文消息的摘要，仅有单图文消息才有摘要，多图文此处为空
                show_cover_pic	是	是否显示封面，0为false，即不显示，1为true，即显示
                content	是	图文消息的具体内容，支持HTML标签，必须少于2万字符，小于1M，且此处会去除JS
                content_source_url	是	图文消息的原文地址，即点击“阅读原文”后的URL
        :return: 新增的图文消息素材的media_id
        """
        res = self.request.post(
            "https://api.weixin.qq.com/cgi-bin/material/add_news",
            data=data
        )
        return res.get('media_id')

    def uploadimg(self, media):
        """
        上传图文消息内的图片获取URL
        :param media: str|tuple 传入 图片的url 或者（filename、img bytes、content-type）
        :return: 上传图片的URL，可用于后续群发中，放置到图文消息中。
        """
        if isinstance(media, str):
            r_img = requests.get(media)
            content_type = r_img.headers['Content-Type']
            media_img = (random_char() + mimetypes.guess_extension(content_type), BytesIO(r_img.content), content_type)
        else:
            media_img = media

        res = self.request.post(
            "https://api.weixin.qq.com/cgi-bin/material/add_material",
            params={
                'type': 'image'
            },
            files={
                'media': media_img
            }
        )
        return res['url']

    def get_material(self, media_id):
        """
        获取永久素材
        :param media_id: 要获取的素材的media_id
        :return: 詳情請查看官方文檔 http://mp.weixin.qq.com/wiki/12/3c12fac7c14cb4d0e0d4fe2fbc87b638.html
        """
        res = self.request.post(
            'https://api.weixin.qq.com/cgi-bin/material/get_material',
            data={"media_id": media_id}
        )
        return res

    def batchget_material(self, media_type, offset, count):
        """
        获取素材列表
        :param media_type: 素材的类型，图片（image）、视频（video）、语音 （voice）、图文（news）
        :param offset: 从全部素材的该偏移位置开始返回，0表示从第一个素材 返回
        :param count: 返回素材的数量，取值在1到20之间
        :return: http://mp.weixin.qq.com/wiki/15/8386c11b7bc4cdd1499c572bfe2e95b3.html
        """
        res = self.request.post(
            'https://api.weixin.qq.com/cgi-bin/material/batchget_material',
            data={"type": media_type, 'offset': offset, 'count': count}
        )
        return res
